package com.zenithmind.document.pojo.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.zenithmind.common.base.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

import jakarta.validation.constraints.*;
import java.time.LocalDateTime;

/**
 * 文档聚合根
 * 遵循单一职责原则：专注于文档基本信息管理
 * 遵循封装原则：通过方法控制状态变更
 * 遵循开闭原则：支持文档类型和状态扩展
 *
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@EqualsAndHashCode(callSuper = true)
@Getter
@NoArgsConstructor
@TableName("document")
@Schema(description = "文档聚合根")
public class Document extends BaseEntity {

    /**
     * 文档状态枚举
     */
    public enum DocumentStatus {
        PROCESSING(0, "处理中"),
        NORMAL(1, "正常"),
        DELETED(2, "已删除"),
        FAILED(3, "处理失败");

        private final int code;
        private final String description;

        DocumentStatus(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static DocumentStatus fromCode(int code) {
            for (DocumentStatus status : values()) {
                if (status.code == code) {
                    return status;
                }
            }
            throw new IllegalArgumentException("未知的文档状态代码: " + code);
        }
    }

    /**
     * 访问权限枚举
     */
    public enum AccessLevel {
        PRIVATE(0, "私有"),
        PUBLIC(1, "公开"),
        DEPARTMENT(2, "部门"),
        SPECIFIED_USERS(3, "指定用户");

        private final int code;
        private final String description;

        AccessLevel(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static AccessLevel fromCode(int code) {
            for (AccessLevel level : values()) {
                if (level.code == code) {
                    return level;
                }
            }
            throw new IllegalArgumentException("未知的访问权限代码: " + code);
        }
    }

    /**
     * 文档来源枚举
     */
    public enum DocumentSource {
        UPLOAD(1, "上传"),
        CREATE(2, "创建"),
        CONVERT(3, "转换"),
        IMPORT(4, "导入");

        private final int code;
        private final String description;

        DocumentSource(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public int getCode() { return code; }
        public String getDescription() { return description; }

        public static DocumentSource fromCode(int code) {
            for (DocumentSource source : values()) {
                if (source.code == code) {
                    return source;
                }
            }
            throw new IllegalArgumentException("未知的文档来源代码: " + code);
        }
    }

    // ========== 基本信息字段 ==========

    /**
     * 文档名称
     */
    @NotBlank(message = "文档名称不能为空")
    @Size(max = 200, message = "文档名称长度不能超过200个字符")
    @TableField("name")
    @Schema(description = "文档名称")
    private String name;

    /**
     * 文档标题
     */
    @Size(max = 500, message = "文档标题长度不能超过500个字符")
    @TableField("title")
    @Schema(description = "文档标题")
    private String title;

    /**
     * 文档描述
     */
    @Size(max = 2000, message = "文档描述长度不能超过2000个字符")
    @TableField("description")
    @Schema(description = "文档描述")
    private String description;

    /**
     * 文档类型（pdf, doc, docx, xls, xlsx, ppt, pptx等）
     */
    @NotBlank(message = "文档类型不能为空")
    @Size(max = 50, message = "文档类型长度不能超过50个字符")
    @TableField("type")
    @Schema(description = "文档类型")
    private String type;

    /**
     * 文档分类ID
     */
    @TableField("category_id")
    @Schema(description = "文档分类ID")
    private String categoryId;

    /**
     * 文档标签（JSON格式）
     */
    @TableField("tags")
    @Schema(description = "文档标签（JSON格式）")
    private String tags;

    /**
     * 文件大小（字节）
     */
    @TableField("file_size")
    @Schema(description = "文件大小（字节）")
    private Long fileSize;

    /**
     * 文件路径
     */
    @TableField("file_path")
    @Schema(description = "文件路径")
    private String filePath;

    /**
     * 文件URL
     */
    @TableField("file_url")
    @Schema(description = "文件URL")
    private String fileUrl;

    /**
     * 缩略图URL
     */
    @TableField("thumbnail_url")
    @Schema(description = "缩略图URL")
    private String thumbnailUrl;

    /**
     * 预览URL
     */
    @TableField("preview_url")
    @Schema(description = "预览URL")
    private String previewUrl;

    /**
     * 文档内容（提取的文本内容）
     */
    @TableField("content")
    @Schema(description = "文档内容")
    private String content;

    /**
     * 文档摘要
     */
    @TableField("summary")
    @Schema(description = "文档摘要")
    private String summary;

    /**
     * 关键词
     */
    @TableField("keywords")
    @Schema(description = "关键词")
    private String keywords;

    /**
     * 文档状态
     */
    @NotNull(message = "文档状态不能为空")
    @TableField("status")
    @Schema(description = "文档状态")
    private Integer status;

    /**
     * 文档版本号
     */
    @TableField("version")
    @Schema(description = "文档版本号")
    private String version;

    /**
     * 父文档ID（用于版本控制）
     */
    @TableField("parent_id")
    @Schema(description = "父文档ID")
    private String parentId;

    /**
     * 是否为最新版本
     */
    @TableField("is_latest")
    @Schema(description = "是否为最新版本")
    private Integer isLatest;

    /**
     * 访问权限（0:私有, 1:公开, 2:部门, 3:指定用户）
     */
    @TableField("access_level")
    @Schema(description = "访问权限")
    private Integer accessLevel;

    /**
     * 权限配置（JSON格式）
     */
    @TableField("permission_config")
    @Schema(description = "权限配置（JSON格式）")
    private String permissionConfig;

    /**
     * 是否加密
     */
    @TableField("is_encrypted")
    @Schema(description = "是否加密")
    private Integer isEncrypted;

    /**
     * 加密算法
     */
    @TableField("encryption_algorithm")
    @Schema(description = "加密算法")
    private String encryptionAlgorithm;

    /**
     * 文档来源（1:上传, 2:创建, 3:转换, 4:导入）
     */
    @TableField("source")
    @Schema(description = "文档来源")
    private Integer source;

    /**
     * 原始文件名
     */
    @TableField("original_name")
    @Schema(description = "原始文件名")
    private String originalName;

    /**
     * MIME类型
     */
    @TableField("mime_type")
    @Schema(description = "MIME类型")
    private String mimeType;

    /**
     * MD5哈希值
     */
    @TableField("md5_hash")
    @Schema(description = "MD5哈希值")
    private String md5Hash;

    /**
     * 页数（适用于PDF等）
     */
    @TableField("page_count")
    @Schema(description = "页数")
    private Integer pageCount;

    /**
     * 字数统计
     */
    @TableField("word_count")
    @Schema(description = "字数统计")
    private Integer wordCount;

    /**
     * 语言
     */
    @TableField("language")
    @Schema(description = "语言")
    private String language;

    /**
     * 创建者ID
     */
    @TableField("creator_id")
    @Schema(description = "创建者ID")
    private String creatorId;

    /**
     * 最后修改者ID
     */
    @TableField("last_modifier_id")
    @Schema(description = "最后修改者ID")
    private String lastModifierId;

    /**
     * 下载次数
     */
    @TableField("download_count")
    @Schema(description = "下载次数")
    private Long downloadCount;

    /**
     * 查看次数
     */
    @TableField("view_count")
    @Schema(description = "查看次数")
    private Long viewCount;

    /**
     * 收藏次数
     */
    @TableField("favorite_count")
    @Schema(description = "收藏次数")
    private Long favoriteCount;

    /**
     * 评分
     */
    @TableField("rating")
    @Schema(description = "评分")
    private Double rating;

    /**
     * 评分次数
     */
    @TableField("rating_count")
    @Schema(description = "评分次数")
    private Long ratingCount;

    /**
     * 最后访问时间
     */
    @TableField("last_access_time")
    @Schema(description = "最后访问时间")
    private LocalDateTime lastAccessTime;

    /**
     * 过期时间
     */
    @TableField("expire_time")
    @Schema(description = "过期时间")
    private LocalDateTime expireTime;

    /**
     * 扩展属性（JSON格式）
     */
    @TableField("extra_properties")
    @Schema(description = "扩展属性（JSON格式）")
    private String extraProperties;

    // ========== 业务方法 ==========

    /**
     * 创建文档
     * 遵循单一职责原则：专注于文档创建逻辑
     */
    public static Document create(String name, String title, String type, String categoryId, String creatorId) {
        Document document = new Document();
        document.setName(name);
        document.setTitle(title);
        document.setType(type);
        document.setCategoryId(categoryId);
        document.setCreatorId(creatorId);
        document.setStatus(DocumentStatus.PROCESSING.getCode());
        document.setAccessLevel(AccessLevel.PRIVATE.getCode());
        document.setSource(DocumentSource.CREATE.getCode());
        document.setIsLatest(1);
        document.setIsEncrypted(0);
        return document;
    }

    /**
     * 设置文档名称（带验证）
     */
    public void setName(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("文档名称不能为空");
        }
        if (name.length() > 200) {
            throw new IllegalArgumentException("文档名称长度不能超过200个字符");
        }
        this.name = name.trim();
    }

    /**
     * 设置文档标题（带验证）
     */
    public void setTitle(String title) {
        if (title != null && title.length() > 500) {
            throw new IllegalArgumentException("文档标题长度不能超过500个字符");
        }
        this.title = title;
    }

    /**
     * 设置文档类型（带验证）
     */
    public void setType(String type) {
        if (type == null || type.trim().isEmpty()) {
            throw new IllegalArgumentException("文档类型不能为空");
        }
        if (type.length() > 50) {
            throw new IllegalArgumentException("文档类型长度不能超过50个字符");
        }
        this.type = type.trim().toLowerCase();
    }

    /**
     * 设置创建者ID
     */
    public void setCreatorId(String creatorId) {
        if (creatorId == null || creatorId.trim().isEmpty()) {
            throw new IllegalArgumentException("创建者ID不能为空");
        }
        this.creatorId = creatorId;
    }

    /**
     * 设置最后修改者ID
     */
    public void setLastModifierId(String lastModifierId) {
        if (lastModifierId == null || lastModifierId.trim().isEmpty()) {
            throw new IllegalArgumentException("最后修改者ID不能为空");
        }
        this.lastModifierId = lastModifierId;
    }

    /**
     * 设置文档状态
     */
    public void setStatus(Integer status) {
        if (status == null) {
            throw new IllegalArgumentException("文档状态不能为空");
        }
        // 验证状态值是否有效
        DocumentStatus.fromCode(status);
        this.status = status;
    }

    /**
     * 设置访问权限
     */
    public void setAccessLevel(Integer accessLevel) {
        if (accessLevel == null) {
            throw new IllegalArgumentException("访问权限不能为空");
        }
        // 验证权限值是否有效
        AccessLevel.fromCode(accessLevel);
        this.accessLevel = accessLevel;
    }

    /**
     * 设置文档来源
     */
    public void setSource(Integer source) {
        if (source == null) {
            throw new IllegalArgumentException("文档来源不能为空");
        }
        // 验证来源值是否有效
        DocumentSource.fromCode(source);
        this.source = source;
    }

    /**
     * 设置文档分类ID
     */
    public void setCategoryId(String categoryId) {
        this.categoryId = categoryId;
    }

    /**
     * 设置是否为最新版本
     */
    public void setIsLatest(Integer isLatest) {
        this.isLatest = isLatest;
    }

    /**
     * 设置是否加密
     */
    public void setIsEncrypted(Integer isEncrypted) {
        this.isEncrypted = isEncrypted;
    }

    /**
     * 设置文档描述
     */
    public void setDescription(String description) {
        if (description != null && description.length() > 2000) {
            throw new IllegalArgumentException("文档描述长度不能超过2000个字符");
        }
        this.description = description;
    }

    /**
     * 设置文件大小
     */
    public void setFileSize(Long fileSize) {
        if (fileSize != null && fileSize < 0) {
            throw new IllegalArgumentException("文件大小不能为负数");
        }
        this.fileSize = fileSize;
    }

    /**
     * 设置文件路径
     */
    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    /**
     * 设置文件URL
     */
    public void setFileUrl(String fileUrl) {
        this.fileUrl = fileUrl;
    }

    /**
     * 设置原始文件名
     */
    public void setOriginalName(String originalName) {
        this.originalName = originalName;
    }

    /**
     * 设置MIME类型
     */
    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    /**
     * 设置MD5哈希值
     */
    public void setMd5Hash(String md5Hash) {
        this.md5Hash = md5Hash;
    }

    /**
     * 设置文档内容
     */
    public void setContent(String content) {
        this.content = content;
    }

    /**
     * 设置文档摘要
     */
    public void setSummary(String summary) {
        this.summary = summary;
    }

    /**
     * 设置关键词
     */
    public void setKeywords(String keywords) {
        this.keywords = keywords;
    }

    /**
     * 设置文档版本号
     */
    public void setVersion(String version) {
        this.version = version;
    }

    /**
     * 设置缩略图URL
     */
    public void setThumbnailUrl(String thumbnailUrl) {
        this.thumbnailUrl = thumbnailUrl;
    }

    /**
     * 设置预览URL
     */
    public void setPreviewUrl(String previewUrl) {
        this.previewUrl = previewUrl;
    }

    /**
     * 设置父文档ID
     */
    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    /**
     * 设置加密算法
     */
    public void setEncryptionAlgorithm(String encryptionAlgorithm) {
        this.encryptionAlgorithm = encryptionAlgorithm;
    }

    /**
     * 获取文档状态枚举
     */
    public DocumentStatus getDocumentStatus() {
        return status != null ? DocumentStatus.fromCode(status) : null;
    }

    /**
     * 获取访问权限枚举
     */
    public AccessLevel getAccessLevelEnum() {
        return accessLevel != null ? AccessLevel.fromCode(accessLevel) : null;
    }

    /**
     * 获取文档来源枚举
     */
    public DocumentSource getDocumentSource() {
        return source != null ? DocumentSource.fromCode(source) : null;
    }

    /**
     * 检查文档是否为正常状态
     */
    public boolean isNormal() {
        return DocumentStatus.NORMAL.getCode() == (status != null ? status : -1);
    }

    /**
     * 检查文档是否已删除
     */
    public boolean isDeleted() {
        return DocumentStatus.DELETED.getCode() == (status != null ? status : -1);
    }

    /**
     * 检查文档是否为公开访问
     */
    public boolean isPublic() {
        return AccessLevel.PUBLIC.getCode() == (accessLevel != null ? accessLevel : -1);
    }

    /**
     * 检查文档是否为最新版本
     */
    public boolean isLatestVersion() {
        return Integer.valueOf(1).equals(isLatest);
    }

    /**
     * 检查文档是否已加密
     */
    public boolean isEncrypted() {
        return Integer.valueOf(1).equals(isEncrypted);
    }

    /**
     * 检查文档是否已过期
     */
    public boolean isExpired() {
        return expireTime != null && LocalDateTime.now().isAfter(expireTime);
    }

    /**
     * 标记为已删除
     */
    public void markAsDeleted() {
        this.status = DocumentStatus.DELETED.getCode();
    }

    /**
     * 恢复文档
     */
    public void restore() {
        this.status = DocumentStatus.NORMAL.getCode();
    }

    /**
     * 标记为处理失败
     */
    public void markAsFailed() {
        this.status = DocumentStatus.FAILED.getCode();
    }

    /**
     * 标记为正常
     */
    public void markAsNormal() {
        this.status = DocumentStatus.NORMAL.getCode();
    }

    /**
     * 设置为最新版本
     */
    public void setAsLatest() {
        this.isLatest = 1;
    }

    /**
     * 设置为非最新版本
     */
    public void setAsNotLatest() {
        this.isLatest = 0;
    }

    /**
     * 更新访问时间
     */
    public void updateLastAccessTime() {
        this.lastAccessTime = LocalDateTime.now();
    }

    /**
     * 验证文档基本信息是否完整
     */
    public boolean isBasicInfoComplete() {
        return name != null && !name.trim().isEmpty() &&
               type != null && !type.trim().isEmpty() &&
               creatorId != null && !creatorId.trim().isEmpty();
    }

    /**
     * 获取文件扩展名
     */
    public String getFileExtension() {
        if (originalName != null && originalName.contains(".")) {
            return originalName.substring(originalName.lastIndexOf(".") + 1).toLowerCase();
        }
        return type != null ? type.toLowerCase() : "";
    }

    /**
     * 格式化文件大小
     */
    public String getFormattedFileSize() {
        if (fileSize == null || fileSize <= 0) {
            return "0 B";
        }

        String[] units = {"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double size = fileSize.doubleValue();

        while (size >= 1024 && unitIndex < units.length - 1) {
            size /= 1024;
            unitIndex++;
        }

        return String.format("%.2f %s", size, units[unitIndex]);
    }
}
